GOHOSTOS:=$(shell go env GOHOSTOS)
GOPATH:=$(shell go env GOPATH)
VERSION=$(shell git describe --tags --always)

PROJECT_NAME := helloworld
IMAGE_NAME := $(PROJECT_NAME)
CONTAINER_NAME := $(PROJECT_NAME)
DOCKERFILE := Dockerfile

# make临时目录 废弃，下载慢
MAKE_DIR=$(shell pwd)/.make
MAKE_PROTOC_DIR=${MAKE_DIR}/protoc
MAKE_PROTO_DIR=${MAKE_DIR}/proto

PROTOBUF_VERSION=3.17.3

WS_PORT=7000
GRPC_PORT=9000
HTTP_PORT=8000
LOGS_DIR=logs
CONF_DIR=configs

# Docker镜像标签
IMAGE_TAG := $(IMAGE_NAME):$(VERSION)
LATEST_TAG := $(IMAGE_NAME):latest


ifeq ($(GOHOSTOS), windows)
	#the `find.exe` is different from `find` in bash/shell.
	#to see https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/find.
	#changed to use git-bash.exe to run find cli or other cli friendly, caused of every developer has a Git.
	#Git_Bash= $(subst cmd\,bin\bash.exe,$(dir $(shell where git)))
	Git_Bash=$(subst \,/,$(subst cmd\,bin\bash.exe,$(dir $(shell where git))))
	INTERNAL_PROTO_FILES=$(shell $(Git_Bash) -c "find internal -name *.proto")
	API_PROTO_FILES=$(shell $(Git_Bash) -c "find api -name *.proto")
else
	INTERNAL_PROTO_FILES=$(shell find internal -name *.proto)
	API_PROTO_FILES=$(shell find api -name *.proto)
endif

.PHONY: init
# init env
init:
	go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
	go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
	go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
	go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest
	go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest
	go install github.com/google/wire/cmd/wire@latest
	go install gitee.com/carlzyhuang/framework/rpc/websocket/protoc-gen-go-websocket@latest

.PHONY: config
# generate internal proto
config:
	protoc --proto_path=./internal \
	       --proto_path=./third_party \
 	       --go_out=paths=source_relative:./internal \
	       $(INTERNAL_PROTO_FILES)

.PHONY: api
# generate api proto
api:
	protoc --proto_path=./api \
	       --proto_path=./third_party \
 	       --go_out=paths=source_relative:./api \
 	       --go-http_out=paths=source_relative:./api \
 	       --go-grpc_out=paths=source_relative:./api \
	       --openapi_out=fq_schema_naming=true,default_response=false:. \
	       $(API_PROTO_FILES)

api-ws:
	@echo "generate api ws proto files..."
	protoc --proto_path=./api \
	       --proto_path=./third_party \
 	       --go_out=paths=source_relative:./api \
 	       --go-websocket_out=paths=source_relative:./api \
	       $(API_PROTO_FILES)

.PHONY: build
# build
build:
	@echo "Building version: $(VERSION)"
	mkdir -p bin/ && go build -ldflags "-X main.Version=$(VERSION)" -o ./bin/  ./...

.PHONY: generate
# generate
generate:
	go generate ./...
	go mod tidy

.PHONY: all
# generate all
all:
	make api;
	make config;
	make generate;
	make build;
	make image;

# 构建Docker镜像
image: check-docker
	@echo "构建Docker镜像: $(IMAGE_TAG)"
	docker build --build-arg PROJECT_NAME=$(PROJECT_NAME) -t $(IMAGE_TAG) -t $(LATEST_TAG) -f $(DOCKERFILE) .

# 重新构建镜像（不使用缓存）
rebuild-image: check-docker
	@echo "重新构建Docker镜像（不使用缓存）: $(IMAGE_TAG)"
	docker build --no-cache -t $(IMAGE_TAG) -t $(LATEST_TAG) -f $(DOCKERFILE) .


# 检查Docker是否可用
check-docker:
	@which docker > /dev/null || (echo "错误: Docker未安装" && exit 1)

# 运行容器（前台模式，用于调试）
run: check-docker
	@echo "运行容器（前台模式）..."
	docker run -it --rm \
		--name $(CONTAINER_NAME) \
		-p $(WS_PORT):7000 \
		-p $(GRPC_PORT):9000 \
		-p $(HTTP_PORT):8000 \
		-v $(PWD)/$(CONF_DIR):/data/conf:ro \
		-v $(PWD)/$(LOGS_DIR):/app/logs/ \
		$(IMAGE_TAG)

# 启动容器（后台模式）
start: check-docker
	@echo "启动容器（后台模式）..."
	docker run -d \
		--name $(CONTAINER_NAME) \
		-p $(WS_PORT):7000 \
		-p $(GRPC_PORT):9000 \
		-p $(HTTP_PORT):8000 \
		-v $(PWD)/$(CONF_DIR):/data/conf:ro \
		-v $(PWD)/$(LOGS_DIR):/app/logs/ \
		$(IMAGE_TAG)
	@echo "容器已启动，访问 http://localhost:$(HTTP_PORT)"

# 停止容器
stop: check-docker
	@echo "停止容器..."
	-docker stop $(CONTAINER_NAME)

# 删除容器
clean: stop clean-make
	@echo "删除容器..."
	@docker rm $(CONTAINER_NAME)


clean-make:
	@echo "清理make临时目录..."
	@rm -rf ${MAKE_DIR}

# 检查并下载protoc编译器，用于下载指定版本，手动拷贝到path目录
proto-bin:
	@echo "check and downloading protoc version ${PROTOBUF_VERSION}... to ${MAKE_PROTO_DIR}"
	@mkdir -p ${MAKE_PROTO_DIR}
	@if test ! -d ${MAKE_PROTOC_DIR}; then \
		export GOBIN=${MAKE_PROTOC_DIR}/bin ;\
		mkdir -p ${MAKE_PROTOC_DIR}/bin ;\
		wget -q https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip ;\
		unzip protoc-${PROTOBUF_VERSION}-linux-x86_64.zip -x readme.txt -d ${MAKE_PROTOC_DIR} && rm -rf protoc-${PROTOBUF_VERSION}-linux-x86_64.zip ;\
		mv -f ${MAKE_PROTOC_DIR}/include/google ${MAKE_PROTO_DIR} && rm -rf ${MAKE_PROTOC_DIR}/include;\
	fi

# show help
help:
	@echo ''
	@echo 'Usage:'
	@echo ' make [target]'
	@echo ''
	@echo 'Targets:'
	@awk  '/^[a-zA-Z\-_0-9]+:/ { \
	helpMessage = match(lastLine, /^# (.*)/); \
		if (helpMessage) { \
			helpCommand = substr($$1, 0, index($$1, ":")); \
			helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \
			printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \
		} \
	} \
	{ lastLine = $$0 }' $(MAKEFILE_LIST)

.DEFAULT_GOAL := help
